package com.another.common.utils.common;

import com.alibaba.fastjson.JSON;
import com.another.common.utils.base.entity.BaseEntity;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * json压缩工具类
 *
 * @author zhengxin
 */
public class JSONH {

    private static final String NULL_STR = "null";


    /**
     * 将list压缩为json串
     * @param list
     * @param <E>
     * @return
     */
    public static <E extends BaseEntity> String pack(List<E> list){
        if(list == null || list.size() == 0){
            return null;
        }
        Class<?> clazz = list.get(0).getClass();
        // 获取所有属性
        Field[] fields = clazz.getDeclaredFields();

        List result = new ArrayList<>();
        // 属性长度放入result
        result.add(fields.length);
        // 属性名称放入result
        Arrays.stream(fields).forEach(item -> {
            // 打开私有访问
            item.setAccessible(true);
            result.add(item.getName());
        });
        // 循环取出list中对象值放入result
        list.stream().forEach(item -> Arrays.stream(fields).forEach(lambdaWrapper(field -> {}, item, result)));

        return JSON.toJSONString(result);
//        return pack(JSON.toJSONString(list));
    }

    /**
     * 异常处理封装
     * @param consumer
     * @param entity
     * @param result
     * @return
     */
    private static Consumer<Field> lambdaWrapper(Consumer<Field> consumer, BaseEntity entity, List result){
        return field -> {
            try {
                result.add(field.get(entity));
                consumer.accept(field);
            }catch (IllegalAccessException ex){
                ex.printStackTrace();
            }
        };
    }

    /**
     * 将json串（原始数据为{@code List<E>}）压缩
     * @param json
     * @return
     */
    public static String pack(String json){
        if(StringUtils.isBlank(json)){
            return null;
        }

        // 获取列表数据中所有key
        List<Map> list = JSON.parseArray(json, Map.class);
        Stream<Object> keyStream = list.stream().flatMap(item -> item.keySet().stream());
        List<String> keys = keyStream.map(item -> String.valueOf(item)).distinct().filter(item ->
                !NULL_STR.equals(item) && StringUtils.isNotBlank(item)).collect(Collectors.toList());

        List result = new ArrayList();
        // 属性长度放入result
        result.add(keys.size());
        // 属性名称放入result
        result.addAll(keys);
        // 循环取出list中map的key对应值放入result
        list.stream().forEach(item -> keys.stream().forEach(key -> result.add(item.get(key))));

        return JSON.toJSONString(result);
    }


    /**
     *  将压缩过的json解压
     * @param json
     * @return
     */
    public static String unpack(String json){
        if(StringUtils.isBlank(json)){
            return null;
        }
        List<String> list = JSON.parseArray(json, String.class);
        if(list == null || list.size() < 2){
            return null;
        }

        // 获取第一条数据，作为每条数据key的总数
        int length = Integer.parseInt(list.remove(0));
        // 根据key的总数切分list
        List<List<String>> dataList = new SplitListUtil<String>().split(list, length);
        // 获取第一个list作为keys
        List<String> keys = dataList.remove(0);
        // 将每条数据转为map，并放入result中
        List<Map> result = dataList.stream().map(item -> createMap(keys, item)).collect(Collectors.toList());

        return JSON.toJSONString(result);
    }

    /**
     * 将两个list按照顺序将值放入map中
     * @param keys
     * @param values
     * @return
     */
    private static Map createMap(List keys, List values){
        Map map = new HashMap();
        for(int i=0; i < keys.size(); i++){
            map.put(keys.get(i), values.get(i));
        }
        return map;
    }

    public static void main(String[] args){

        List list = new ArrayList();
        Map map1 = new HashMap();
        map1.put("a", "123456");
        map1.put("b", 12);
        Map map2 = new HashMap();
        map2.put("b", 12);
        map2.put("c", 12);
        list.add(map1);
        list.add(map2);

        // [[a,b,c],[12,12,null],[null,12,12]]
        // [3,a,b,c,12,12,null,null,12,12]

        List list2 = new ArrayList();
        list2.add("xxx");
        list2.add("yyy");
        map1.put("c", list2);
        String pack = pack(JSON.toJSONString(list));
        System.out.println(pack);
        String unpack = unpack(pack);
        System.out.println(unpack);

        BaseEntity entity = new BaseEntity();
        entity.setRequestCompanyId("requestCompanyId");
        entity.setRequestUserId("requestUserId");
        BaseEntity entity2 = new BaseEntity();
        entity2.setRequestCompanyId("requestCompanyId");
        entity2.setRequestUserId("requestUserId");
        List list3 = new ArrayList();
        list3.add(entity);
        list3.add(entity2);
        String pack1 = pack(list3);
        System.out.println(pack1);

        Stream<String> s1 = Stream.of("aa", "ab", "c", "ad");
//        System.out.println(s1.reduce(new ArrayList<String>(), (r, t) -> {r.add(t); return r; }, (r1, r2) -> r1));
        System.out.println(s1.reduce(new ArrayList<String>(), (r, t) -> {r.add(t); return r; }, (r1, r2) -> r2));

    }
}
